#include <rtthread.h>
#include <rtdevice.h>
#include "host.h"

#define CAN_DEV_NAME       "can1"      /* CAN 设备名称 */

static struct rt_semaphore rx_sem;     /* 用于接收消息的信号量 */
static rt_device_t can_dev;            /* CAN 设备句柄 */

static rt_uint8_t slaver_heartbeat[16];
rt_int32_t sensor_temp[16];
rt_uint32_t slaver_online;

static void slaver_detect(rt_uint8_t slaver_id)
{
    slaver_heartbeat[slaver_id] = 100;
    for(rt_uint8_t i = 0; i < 16; i++)
    {
        if(slaver_heartbeat[i] > 0)
        { 
            rt_atomic_or(&slaver_online, (1 << i));
            slaver_heartbeat[i]--;
        }
        else
        {
            rt_atomic_and(&slaver_online, ~(1 << i));
        }
    }
}

/* 接收数据回调函数 */
static rt_err_t can_rx_call(rt_device_t dev, rt_size_t size)
{
    /* CAN 接收到数据后产生中断，调用此回调函数，然后发送接收信号量 */
    rt_sem_release(&rx_sem);

    return RT_EOK;
}

static void can_rx_thread(void *parameter)
{
    rt_err_t res;
    struct rt_can_msg rxmsg = {0};

    /* 设置接收回调函数 */
    rt_device_set_rx_indicate(can_dev, can_rx_call);

#ifdef RT_CAN_USING_HDR
    struct rt_can_filter_item items[5] =
    {
        RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 0, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x100~0x1ff，hdr 为 - 1，设置默认过滤表 */
        RT_CAN_FILTER_ITEM_INIT(0x300, 0, 0, 0, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x300~0x3ff，hdr 为 - 1 */
        RT_CAN_FILTER_ITEM_INIT(0x211, 0, 0, 0, 0x7ff, RT_NULL, RT_NULL), /* std,match ID:0x211，hdr 为 - 1 */
        RT_CAN_FILTER_STD_INIT(0x486, RT_NULL, RT_NULL),                  /* std,match ID:0x486，hdr 为 - 1 */
        {0x555, 0, 0, 0, 0x7ff, 7,}                                       /* std,match ID:0x555，hdr 为 7，指定设置 7 号过滤表 */
    };
    struct rt_can_filter_config cfg = {5, 1, items}; /* 一共有 5 个过滤表 */
    /* 设置硬件过滤表 */
    res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg);
    RT_ASSERT(res == RT_EOK);
#endif

    while (1)
    {
        /* 阻塞等待接收信号量 */
        rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
        /* 从 CAN 读取一帧数据 */
        rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg));
        // /* 打印数据 ID 及内容 */
        // rt_kprintf("ID:%x", rxmsg.id);
        // for (rt_uint8_t i = 0; i < 8; i++)
        // {
        //     rt_kprintf("%2x", rxmsg.data[i]);
        // }
        // rt_kprintf("\n");
        slaver_detect(rxmsg.id);

        if(rxmsg.data[0] == CAN_PROTOCOL_DATA)
        {
            switch(rxmsg.data[1])
            {
                case CAN_Data_PV:
                    rt_atomic_store(&sensor_temp[rxmsg.id], *(rt_int32_t *)&rxmsg.data[2]);
                    // rt_kprintf("temp[%d]:%ld\n", rxmsg.id, sensor_temp[rxmsg.id]);
                    break;
            }
        }
    }
}

static void can_send_bytes(rt_uint32_t id, rt_uint8_t *data, rt_uint8_t len)
{
    struct rt_can_msg msg = {0};
    rt_size_t  size;
    
    msg.id = id;                    /* ID */
    msg.ide = RT_CAN_STDID;         /* 标准格式 */
    msg.rtr = RT_CAN_DTR;           /* 数据帧 */
    msg.len = len;                  /* 数据长度 */
    if(len > 8)
    {
        rt_kprintf("can send data len is too long!\n");
    }
    /* 待发送的 8 字节数据 */
    rt_memcpy(msg.data, data, len);
    /* 发送一帧 CAN 数据 */
    size = rt_device_write(can_dev, 0, &msg, sizeof(msg));
    if (size == 0)
    {
        rt_kprintf("can dev write data failed!\n");
    }
}
// void can_send_cmd(rt_uint32_t can_id, rt_uint8_t cmd_id)
// {
//     rt_uint8_t buf[2];
//     buf[0] = CAN_PROTOCOL_CMD;
//     buf[1] = cmd_id;
//     can_send_bytes(can_id, buf, 2);
// }

void can_send_data(rt_uint32_t can_id, rt_uint8_t data_id, rt_uint8_t *data, rt_uint8_t len)
{
    rt_uint8_t buf[8];
    buf[0] = CAN_PROTOCOL_DATA;
    buf[1] = data_id;
    if(len > 6)
    {
        rt_kprintf("can send data len is too long!\n");
    }
    rt_memcpy(&buf[2], data, len);
    can_send_bytes(can_id, buf, len + 2);
}

int thread_can_init(void)
{
    rt_err_t res;
    rt_thread_t thread;

    /* 查找 CAN 设备 */
    can_dev = rt_device_find(CAN_DEV_NAME);
    if (!can_dev)
    {
        rt_kprintf("find %s failed!\n", CAN_DEV_NAME);
        return RT_ERROR;
    }

    /* 初始化 CAN 接收信号量 */
    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);

    /* 以中断接收及发送方式打开 CAN 设备 */
    res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
    RT_ASSERT(res == RT_EOK);
    /* 创建数据接收线程 */
    thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 1024, 15, 10);
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }
    else
    {
        rt_kprintf("create can_rx thread failed!\n");
    }

    return res;
}